<template>
  <div class="awf-container-center">
    <div class="widget-form-container">
      <div v-if="!widgetForm.list" class="form-empty">表单未添加组件</div>
      <a-form layout="vertical" :labelAlign="widgetForm.config.labelAlign" :disabled="true">
        <Draggable
          class="widget-form-list"
          item-key="key"
          ghostClass="ghost"
          handle=".drag-widget"
          :animation="200"
          :group="{ name: 'people' }"
          :list="widgetForm.list"
          @add="handleMoveAdd"
        >
          <template #item="{ element, index }">
            <transition-group name="fade" tag="div">
              <AntdWidgetFormItem
                v-if="element.key"
                :key="element.key"
                class="drag-widget"
                :level="0"
                :element="element"
                :config="widgetForm.config"
                :selectWidget="widgetFormSelect"
                @click="handleItemClick(element)"
                @delete="handleDeleteClick(index, widgetForm.list, element)"
              />
            </transition-group>
          </template>
        </Draggable>
      </a-form>
    </div>
  </div>
</template>

<script lang="ts">
  import { defineComponent, nextTick, PropType, toRaw, inject, Ref } from 'vue';
  import Draggable from 'vuedraggable';
  import AntdWidgetFormItem from './AntdWidgetFormItem.vue';

  import {
    WidgetForm,
    gridComponents,
    TableInfo,
    noHaveTableAndField,
    noHaveField,
  } from '/@/components/Designer/src/types';
  import { buildUUID } from '/@/utils/uuid';
  import { error } from '/@/utils/log';
  import { changeToPinyin, checkTabCanDelete } from '/@/utils/event/design';
  import { random } from 'lodash-es';
  import { notification } from 'ant-design-vue';
  import { useI18n } from '/@/hooks/web/useI18n';
  const { t } = useI18n();

  const handleListDelete = (key: string, list: any[]) => {
    const newList: any[] = [];
    list.forEach((item) => {
      if (item.key !== key) {
        if (item.columns) {
          item.columns = item.columns.map((col: any) => ({
            ...col,
            list: handleListDelete(key, col.list),
          }));
        }
        newList.push(item);
      }
    });
    return newList;
  };

  export default defineComponent({
    name: 'AntdWidgetForm',
    components: {
      Draggable,
      AntdWidgetFormItem,
    },
    props: {
      widgetForm: {
        type: Object as PropType<WidgetForm>,
        required: true,
      },
      widgetFormSelect: {
        type: Object,
      },
    },
    emits: ['update:widgetForm', 'update:widgetFormSelect'],
    setup(props, context) {
      const state = inject('state') as any;
      const tableInfo = inject<Ref<TableInfo[]>>('tableInfo') as Ref<TableInfo[]>;
      const designType = inject<Ref<string>>('designType');

      let mainTableName;
      if (designType?.value !== 'data') {
        mainTableName = inject<string>('mainTableName');
      }

      const handleItemClick = (row: any) => {
        state.widgetFormSelect = row;
      };

      const handleDeleteClick = async (index: number, list: any[], element?) => {
        if (element.options.required) {
          notification.error({
            message: t('提示'),
            description: t('必填的组件不能删除'),
          });
          return;
        } else if (element.type == 'tab' || element.type == 'card' || element.type == 'grid') {
          let str =
            element.type == 'tab' ? '选项卡' : element.type == 'card' ? '卡片布局' : '栅格布局';
          if (checkTabCanDelete(element.layout) > 0) {
            notification.error({
              message: t('提示'),
              description: t(str + '下有不能删除的组件，所以不能删除此' + str),
            });
            return;
          }
        }
        await deleteAdoptedCalc(index, list);
        const oldList = JSON.parse(JSON.stringify(props.widgetForm.list));

        if (list.length - 1 === index) {
          if (index === 0) {
            nextTick(() => context.emit('update:widgetFormSelect', null));
          } else {
            context.emit('update:widgetFormSelect', list[index - 1]);
          }
        } else {
          context.emit('update:widgetFormSelect', list[index + 1]);
        }

        context.emit('update:widgetForm', {
          ...props.widgetForm,
          list: handleListDelete(list[index].key, oldList),
        });
      };

      const handleTabGridDeleteClick = (index: number, list: any[]) => {
        list.splice(index, 1);
      };

      const handleMoveAdd = (event: any) => {
        const list = JSON.parse(JSON.stringify(props.widgetForm.list));
        const { newIndex } = event;

        //判断如果是单表 不支持子表单组件 (仅数据优先时)
        if (
          tableInfo.value.length < 2 &&
          list[newIndex].type === 'form' &&
          designType?.value === 'data'
        ) {
          list.splice(newIndex, 2); //必须2
          context.emit('update:widgetForm', { ...props.widgetForm, list });
          error('单表不能使用子表单组件！');
          return;
        }
        const key = buildUUID().replaceAll('-', '');

        list[newIndex] = {
          ...toRaw(list[newIndex]),
          key,
          model: `${list[newIndex].type}_${key}`,
          rules: [],
        };

        if (
          list[newIndex].type === 'radio' ||
          list[newIndex].type === 'checkbox' ||
          list[newIndex].type === 'select'
        ) {
          list[newIndex] = {
            ...list[newIndex],
            options: {
              ...list[newIndex].options,
              staticOptions: list[newIndex].options.staticOptions.map((item: any) => ({
                ...item,
              })),
            },
          };
        }

        if (list[newIndex].type === 'grid') {
          list[newIndex].layout.map((item: any) => (item.list = []));
          // list[newIndex] = {
          //   ...list[newIndex],
          //   columns: list[newIndex].columns.map((item: any) => ({ ...item }))
          // }
        }

        if (list[newIndex].type === 'form') {
          list[newIndex].children.map((item: any) => (item.list = []));
        }

        if (list[newIndex].type === 'tab') {
          list[newIndex].layout.map((item: any) => (item.list = []));
        }
        //从子表拖入主表时
        list[newIndex].isSubFormChild = false;
        addBindTableAndField(list[newIndex]);

        context.emit('update:widgetForm', { ...props.widgetForm, list });
        context.emit('update:widgetFormSelect', list[newIndex]);
      };

      const handleColMoveAdd = (event: any, row: any, index: string | number | symbol) => {
        const { newIndex, oldIndex, item } = event;
        if (row.type === 'form') {
          const list = JSON.parse(JSON.stringify(props.widgetForm.list));

          if (item.className.includes('data-grid')) {
            item.tagName === 'DIV' && list.splice(oldIndex, 0, row.children[newIndex]);
            row.children[index].splice(newIndex, 1);
            return false;
          }

          const key = buildUUID().replaceAll('-', '');

          row.children[newIndex] = {
            ...toRaw(row.children[index]),
            key,
            model: `${row.children[newIndex].type}_${key}`,
            rules: [],
          };

          if (
            row.children[newIndex].type === 'radio' ||
            row.children[newIndex].type === 'checkbox' ||
            row.children[newIndex].type === 'select'
          ) {
            row.children[newIndex] = {
              ...row.children[newIndex],
              options: {
                ...row.children[newIndex].options,
                staticOptions: row.children[newIndex].options.staticOptions.map((item: any) => ({
                  ...item,
                })),
              },
            };
          }
          context.emit('update:widgetFormSelect', row.children[newIndex]);
        } else {
          const list = JSON.parse(JSON.stringify(props.widgetForm.list));

          if (item.className.includes('data-grid')) {
            item.tagName === 'DIV' && list.splice(oldIndex, 0, row.layout[index].list[newIndex]);
            row.layout[index].list.splice(newIndex, 1);
            return false;
          }

          const key = buildUUID().replaceAll('-', '');

          row.layout[index].list[newIndex] = {
            ...toRaw(row.layout[index].list[newIndex]),
            key,
            model: `${row.layout[index].list[newIndex].type}_${key}`,
            rules: [],
          };

          if (
            row.layout[index].list[newIndex].type === 'radio' ||
            row.layout[index].list[newIndex].type === 'checkbox' ||
            row.layout[index].list[newIndex].type === 'select'
          ) {
            row.layout[index].list[newIndex] = {
              ...row.layout[index].list[newIndex],
              options: {
                ...row.layout[index].list[newIndex].options,
                staticOptions: row.layout[index].list[newIndex].options.staticOptions.map(
                  (item: any) => ({
                    ...item,
                  }),
                ),
              },
            };
          }

          context.emit('update:widgetFormSelect', row.layout[index].list[newIndex]);
        }
      };
      const addBindTableAndField = (component: any) => {
        //界面优先和简易模板
        if (designType?.value !== 'data') {
          //需要绑定字段、组件没有绑定字段的情况下新增绑定字段
          const rangeComponents = ['time-range', 'date-range'];
          if (rangeComponents.includes(component.type)) {
            component.bindStartTime = changeToPinyin(component.label) + random(1000, 9999);
            component.bindEndTime = changeToPinyin(component.label) + random(1000, 9999);
          } else if (!noHaveField.includes(component.type) && !component.bindField) {
            component.bindField = changeToPinyin(component.label) + random(1000, 9999);
          }
          if (component.type === 'form' || component.type === 'one-for-one') {
            component.bindTable = `${mainTableName.value}_child_${random(1000, 9999)}`;
          } else if (!noHaveTableAndField.includes(component.type)) {
            component.bindTable = mainTableName.value;
          }
        }
        if (component.isGridChild) component.options.span = 7;
      };

      //删除引用已删除的财务组件的计算式配置
      const deleteAdoptedCalc = (index: number, list: any[]) => {
        const component = list[index];
        if (['computational', 'money-chinese'].includes(component.type)) {
          component.options.beAdoptedComponent?.map((key) => {
            getLayoutComponent(list, key);
          });
        }
      };

      const getLayoutComponent = (list, key) => {
        list?.map((item) => {
          if (['tab', 'grid', 'card'].includes(item.type)) {
            for (const child of item.layout!) {
              getLayoutComponent(child.list, key);
            }
          } else if (item.type === 'form') {
            item.children.map((child: any) => {
              if (['computational', 'money-chinese'].includes(child.type) && child.key === key) {
                child.options.computationalConfig = [];
                child.options.computationalConfigValue = '== 请填写计算式配置 ==';
              }
            });
          } else {
            if (['computational', 'money-chinese'].includes(item.type) && item.key === key) {
              item.options.computationalConfig = [];
              item.options.computationalConfigValue = '== 请填写计算式配置 ==';
            }
          }
        });
      };

      return {
        handleItemClick,

        handleDeleteClick,
        handleTabGridDeleteClick,
        handleMoveAdd,
        handleColMoveAdd,
        gridComponents,
        addBindTableAndField,
      };
    },
  });
</script>
<style scoped lang="less">
  /* @import '/@/assets/style/designer/index.css'; */
  .awf-container-center {
    width: 100%;
    height: 100%;
    box-sizing: border-box;
    border-bottom-left-radius: 26px;
    border-bottom-right-radius: 26px;
  }

  .widget-form-container {
    width: 100%;
    height: 100%;
    background-color: #fff;
    box-sizing: border-box;
  }

  .widget-form-list {
    height: 100%;
  }

  .fc-style .widget-form-container .widget-form-list {
    background: #fff;
    // border: 1px dashed #999;
    min-height: calc(100vh - 305px);
  }
</style>
